package com.sunck.common.shiro;

import com.sunck.common.config.Global;
import com.sunck.common.exception.ResultEnum;
import com.sunck.common.utils.Encodes;
import com.sunck.common.utils.ShiroUtils;
import com.sunck.common.utils.StringUtils;
import com.sunck.modules.system.controller.LoginController;
import com.sunck.modules.system.entity.Menu;
import com.sunck.modules.system.entity.Role;
import com.sunck.modules.system.entity.User;
import com.sunck.modules.system.service.LoginService;
import com.sunck.modules.system.utils.UserUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;

/**
 * 自定义Realm  处理登录、授权
 *
 * @author LengChen
 * @version 1.0
 * @date 2020/8/5
 */
public class UserRealm extends AuthorizingRealm {

    private static final Logger logger = LoggerFactory.getLogger(UserRealm.class);

    @Autowired
    private LoginService loginService;

    /**
     * 获取授权信息
     * @param  principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        User user = ShiroUtils.getSysUser();
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        // 管理员拥有所有权限
        if (user.isAdmin())
        {
            simpleAuthorizationInfo.addRole("admin");
            simpleAuthorizationInfo.addStringPermission("*:*:*");
        }
        else
        {
            /**
             * 添加用户权限，用于登录用户鉴权使用
             */
            simpleAuthorizationInfo.addStringPermission("user");
            if(user.getRoleList()!=null){
                for(Role role : user.getRoleList()){
                    // 角色加入AuthorizationInfo认证对象
                    simpleAuthorizationInfo.addRole(role.getRoleCode());
                    for(Menu menu : role.getMenuList()){
                        if(StringUtils.isNotBlank(menu.getPermission())){
                            // 权限加入AuthorizationInfo认证对象
                            simpleAuthorizationInfo.addStringPermission(menu.getPermission());
                        }
                    }
                }
            }

        }
        return simpleAuthorizationInfo;
    }


    /**
     * 获取认证信息（进行用户认证)
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //加这一步的目的是在Post请求的时候会先进认证，然后在到请求
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        String loginCode = upToken.getUsername();
        String password = "";
        if (upToken.getPassword() != null)
        {
            password = new String(upToken.getPassword());
        }

        if (logger.isDebugEnabled()){
            logger.debug("login submit, active session size: 0, username: {}", loginCode);
        }

        // 校验登录验证码
        if (loginService.isValidateCodeLogin(loginCode, false, false)){
            Session session = UserUtils.getSession();
            String code = String.valueOf(UserUtils.getRemoveCache(Global.DEFAULT_Code_PARAM));
            if (upToken.getValidateCode() == null || !upToken.getValidateCode().equalsIgnoreCase(code)){
                throw new AuthenticationException(ResultEnum.SHIRO_ERROR_2.getStringCode());
            }
        }

        // 用户名或密码为空
        if (org.springframework.util.StringUtils.isEmpty(loginCode) || org.springframework.util.StringUtils.isEmpty(password))
        {
            throw new AuthenticationException(ResultEnum.SHIRO_ERROR_3.getStringCode());
        }

        // 查询用户信息
        User user = loginService.getUserByLoginCode(loginCode);

        if (user == null)
        {
            throw new AuthenticationException(ResultEnum.SHIRO_ERROR_4.getStringCode());
        }
        if (user.DEL_FLAG_DELETE.equals(user.getDelFlag()))
        {
            throw new AuthenticationException(ResultEnum.SHIRO_ERROR_4.getStringCode());
        }
        if ("2".equals(user.getStatus()) || "3".equals(user.getStatus()))
        {
            throw new AuthenticationException(ResultEnum.SHIRO_ERROR_5.getStringCode());
        }

        byte[] salt = Encodes.decodeHex(user.getPassword().substring(0,16));

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
        return simpleAuthenticationInfo;
    }

    /**
     * 设定密码校验的Hash算法与迭代次数
     */
    @PostConstruct
    public void initCredentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("SHA-1");
        matcher.setHashIterations(1024);
        setCredentialsMatcher(matcher);
    }
}
